package coretest;

public class InstructionTest {

	public InstructionTest(){
		this.stringsTest();
	}

	public void byteCodeTest(core.InstructionClass i){
		//ByteCode Part
		core.InstructionClass iaux = new core.InstructionClass(i.getByteCode());
		if (iaux.inst.getFormat() == 4){
			iaux.setByteCode2(i.getByteCode2());
		}
		assert(i.cond == iaux.cond);
/*		System.out.println("Orig: " + i.inst + " Copia: " + iaux.inst);
		System.out.println("Orig: " + i.inst.getOpCode() + " Copia: " + iaux.inst.getOpCode());
		System.out.println("Assembly: " + i.getAssembly());
		System.out.printf("ByteCode: 0x%4x\n", i.getByteCode());*/
		assert(i.inst == iaux.inst);
		assert(i.r_op1 == i.r_op1);
		assert(i.r_op2 == i.r_op2);
		assert(i.r_res == i.r_res);
		assert(i.getAssembly().compareTo(iaux.getAssembly()) == 0);
		
		//Assembly Part:
		iaux = new core.InstructionClass(i.getAssembly());
/*		System.out.println("Assembly: " + i.getAssembly());
		System.out.println("Orig: " + i.inst + " Copia: " + iaux.inst);*/
		assert(i.cond == iaux.cond);
		assert(i.inst == iaux.inst);
		assert(i.r_op1 == i.r_op1);
		assert(i.r_op2 == i.r_op2);
		assert(i.r_res == i.r_res);
		assert(i.getAssembly().compareTo(iaux.getAssembly()) == 0);
	}
	/**
	 * Parser test
	 */
	public void stringsTest(){
		core.InstructionClass i = null;

		//No arguments Instructions:
		i = new core.InstructionClass("asdfasdf");
		assert(i.inst == core.InstructionClass.InstructionType.NOP);
		this.byteCodeTest(i);
		i = new core.InstructionClass("NOP");
		assert(i.inst == core.InstructionClass.InstructionType.NOP);
		this.byteCodeTest(i);
		i = new core.InstructionClass("RET");
		assert(i.inst == core.InstructionClass.InstructionType.RET);
		this.byteCodeTest(i);
		i = new core.InstructionClass("PUSHSR");
		assert(i.inst == core.InstructionClass.InstructionType.PUSHSR);
		this.byteCodeTest(i);
		i = new core.InstructionClass("POPSR");
		assert(i.inst == core.InstructionClass.InstructionType.POPSR);
		this.byteCodeTest(i);
		i = new core.InstructionClass("STOP");
		assert(i.inst == core.InstructionClass.InstructionType.STOP);
		this.byteCodeTest(i);

		//Data movement instructions:
		i = new core.InstructionClass("MOV R1, R2");
		assert(i.inst == core.InstructionClass.InstructionType.MOV);
		assert(i.r_op1 == 1);
		assert(i.r_op2 == 2);
		this.byteCodeTest(i);
		i = new core.InstructionClass("MOV R1, [R2]");
		assert(i.inst == core.InstructionClass.InstructionType.MOVI);
		assert(i.r_op1 == 1);
		assert(i.r_op2 == 2);
		this.byteCodeTest(i);
		i = new core.InstructionClass("MOV [R1], R2");
		assert(i.inst == core.InstructionClass.InstructionType.IMOV);
		assert(i.r_op1 == 1);
		assert(i.r_op2 == 2);
		this.byteCodeTest(i);
		i = new core.InstructionClass("MOV R1, 0x00AB");
		assert(i.inst == core.InstructionClass.InstructionType.MOVM);
		assert(i.r_op1 == 1);
		assert(i.r_op2 == 0x00AB);
		this.byteCodeTest(i);
		i = new core.InstructionClass("MOV 0x00AB, R5");
		assert(i.inst == core.InstructionClass.InstructionType.MMOV);
		assert(i.r_op1 == 5);
		assert(i.r_op2 == 0x00AB);
		this.byteCodeTest(i);
		i = new core.InstructionClass("MVN R2, R3");
		assert(i.inst == core.InstructionClass.InstructionType.MVN);
		assert(i.r_op1 == 2);
		assert(i.r_op2 == 3);
		this.byteCodeTest(i);
		i = new core.InstructionClass("LDR R5, 0x0011");
		assert(i.inst == core.InstructionClass.InstructionType.LDR);
		assert(i.r_op1 == 5);
		assert(i.r_op2 == 0x0011);
		this.byteCodeTest(i);
		i = new core.InstructionClass("SPB R0, R15");
		assert(i.inst == core.InstructionClass.InstructionType.SPB);
		assert(i.r_op1 == 0);
		assert(i.r_op2 == 15);
		this.byteCodeTest(i);
		i = new core.InstructionClass("SPB R0");
		assert(i.inst == core.InstructionClass.InstructionType.NOP);
		this.byteCodeTest(i);
		i = new core.InstructionClass("MLB R0, R15");
		assert(i.inst == core.InstructionClass.InstructionType.MLB);
		assert(i.r_op1 == 0);
		assert(i.r_op2 == 15);
		this.byteCodeTest(i);
		i = new core.InstructionClass("MHB R0, R15");
		assert(i.inst == core.InstructionClass.InstructionType.MHB);
		assert(i.r_op1 == 0);
		assert(i.r_op2 == 15);
		this.byteCodeTest(i);

		//Arithmetic Instructions
		i = new core.InstructionClass("ADD R0, R15");
		assert(i.inst == core.InstructionClass.InstructionType.ADD);
		assert(i.r_op1 == 0);
		assert(i.r_op2 == 15);
		this.byteCodeTest(i);
		i = new core.InstructionClass("ADD R0, 0xFFF0");
		assert(i.inst == core.InstructionClass.InstructionType.ADDI);
		assert(i.r_op1 == 0);
		assert(i.r_op2 == (short)0xFFF0);
		this.byteCodeTest(i);
		i = new core.InstructionClass("ADC R0, 0xFFFF");
		assert(i.inst == core.InstructionClass.InstructionType.ADCI);
		assert(i.r_op1 == 0);
		assert(i.r_op2 == (short)0xFFFF);
		this.byteCodeTest(i);
		i = new core.InstructionClass("ADC R0, R1");
		assert(i.inst == core.InstructionClass.InstructionType.ADC);
		assert(i.r_op1 == 0);
		assert(i.r_op2 == 1);
		this.byteCodeTest(i);
		i = new core.InstructionClass("SUB R0, 0xABCD");
		assert(i.inst == core.InstructionClass.InstructionType.SUBI);
		assert(i.r_op1 == 0);
		assert(i.r_op2 == (short)0xABCD);
		this.byteCodeTest(i);
		i = new core.InstructionClass("SUB R10, R12");
		assert(i.inst == core.InstructionClass.InstructionType.SUB);
		assert(i.r_op1 == 10);
		assert(i.r_op2 == 12);
		this.byteCodeTest(i);
		i = new core.InstructionClass("SBC R13, R1");
		assert(i.inst == core.InstructionClass.InstructionType.SBC);
		assert(i.r_op1 == 13);
		assert(i.r_op2 == 1);
		this.byteCodeTest(i);
		i = new core.InstructionClass("SBC R0, 0x0000");
		assert(i.inst == core.InstructionClass.InstructionType.SBCI);
		assert(i.r_op1 == 0);
		assert(i.r_op2 == 0);
		this.byteCodeTest(i);
		i = new core.InstructionClass("INC R14");
		assert(i.inst == core.InstructionClass.InstructionType.INC);
		assert(i.r_op1 == 14);
		this.byteCodeTest(i);
		i = new core.InstructionClass("DEC R0");
		assert(i.inst == core.InstructionClass.InstructionType.DEC);
		assert(i.r_op1 == 0);
		this.byteCodeTest(i);

		//Logic Instructions
		i = new core.InstructionClass("CMP R13, R1");
		assert(i.inst == core.InstructionClass.InstructionType.CMP);
		assert(i.r_op1 == 13);
		assert(i.r_op2 == 1);
		this.byteCodeTest(i);
		i = new core.InstructionClass("AND R13, R1");
		assert(i.inst == core.InstructionClass.InstructionType.AND);
		assert(i.r_op1 == 13);
		assert(i.r_op2 == 1);
		this.byteCodeTest(i);
		i = new core.InstructionClass("OR R13, R1");
		assert(i.inst == core.InstructionClass.InstructionType.OR);
		assert(i.r_op1 == 13);
		assert(i.r_op2 == 1);
		this.byteCodeTest(i);
		i = new core.InstructionClass("XOR R13, R1");
		assert(i.inst == core.InstructionClass.InstructionType.XOR);
		assert(i.r_op1 == 13);
		assert(i.r_op2 == 1);
		this.byteCodeTest(i);
		i = new core.InstructionClass("BIC R13, R1");
		assert(i.inst == core.InstructionClass.InstructionType.BIC);
		assert(i.r_op1 == 13);
		assert(i.r_op2 == 1);
		this.byteCodeTest(i);
		i = new core.InstructionClass("CMP R13, 0xFFFF");
		assert(i.inst == core.InstructionClass.InstructionType.CMPI);
		assert(i.r_op1 == 13);
		assert(i.r_op2 == (short)0xFFFF);
		this.byteCodeTest(i);
		i = new core.InstructionClass("AND R13, 0xFFFF");
		assert(i.inst == core.InstructionClass.InstructionType.ANDI);
		assert(i.r_op1 == 13);
		assert(i.r_op2 == (short)0xFFFF);
		this.byteCodeTest(i);
		i = new core.InstructionClass("OR R13, 0xFFFF");
		assert(i.inst == core.InstructionClass.InstructionType.ORI);
		assert(i.r_op1 == 13);
		assert(i.r_op2 == (short)0xFFFF);
		this.byteCodeTest(i);
		i = new core.InstructionClass("XOR R13, 0xFFFF");
		assert(i.inst == core.InstructionClass.InstructionType.XORI);
		assert(i.r_op1 == 13);
		assert(i.r_op2 == (short)0xFFFF);
		this.byteCodeTest(i);
		i = new core.InstructionClass("BIC R13, 0xFFFF");
		assert(i.inst == core.InstructionClass.InstructionType.BICI);
		assert(i.r_op1 == 13);
		assert(i.r_op2 == (short)0xFFFF);
		this.byteCodeTest(i);
		i = new core.InstructionClass("SHL R13, 0xFF");
		assert(i.inst == core.InstructionClass.InstructionType.NOP);
		this.byteCodeTest(i);
		i = new core.InstructionClass("SHL R13 ,0xF");
		assert(i.inst == core.InstructionClass.InstructionType.SHL);
		assert(i.r_op1 == 13);
		assert(i.r_op2 == (short)0xF);
		this.byteCodeTest(i);
		i = new core.InstructionClass("SHR R13 ,0xF");
		assert(i.inst == core.InstructionClass.InstructionType.SHR);
		assert(i.r_op1 == 13);
		assert(i.r_op2 == (short)0xF);
		this.byteCodeTest(i);
		
		i = new core.InstructionClass("MVN R1, R2");
		assert(i.inst == core.InstructionClass.InstructionType.MVN);
		assert(i.r_op1 == 1);
		assert(i.r_op2 == 2);
		this.byteCodeTest(i);

		//Control Flow
		i = new core.InstructionClass("PUSH R0");
		assert(i.inst == core.InstructionClass.InstructionType.PUSH);
		assert(i.r_op1 == 0);
		this.byteCodeTest(i);
		i = new core.InstructionClass("POP R0");
		assert(i.inst == core.InstructionClass.InstructionType.POP);
		assert(i.r_op1 == 0);
		this.byteCodeTest(i);

		//TEST JUMP and CALL
		i = new core.InstructionClass("JAL [R0]");
		assert(i.inst == core.InstructionClass.InstructionType.JR);
		assert(i.cond == core.InstructionClass.ConditionalCodes.AL);
		assert(i.r_op1 == 0);
		this.byteCodeTest(i);
		i = new core.InstructionClass("JAL 0xFFFF");
		assert(i.inst == core.InstructionClass.InstructionType.J);
		assert(i.cond == core.InstructionClass.ConditionalCodes.AL);
		assert(i.r_op2 == (short)0xFFFF);
		this.byteCodeTest(i);
		i = new core.InstructionClass("CAL [R0]");
		assert(i.inst == core.InstructionClass.InstructionType.CR);
		assert(i.cond == core.InstructionClass.ConditionalCodes.AL);
		assert(i.r_op1 == 0);
		this.byteCodeTest(i);
		i = new core.InstructionClass("CAL 0xFFFF");
		assert(i.inst == core.InstructionClass.InstructionType.C);
		assert(i.cond == core.InstructionClass.ConditionalCodes.AL);
		assert(i.r_op2 == (short)0xFFFF);
		this.byteCodeTest(i);

		//TESTS for each condition (NOT for each condition and instruction):
		i = new core.InstructionClass("CAL 0xFFFF");
		assert(i.cond == core.InstructionClass.ConditionalCodes.AL);
		this.byteCodeTest(i);
		i = new core.InstructionClass("CEQ 0xFFFF");
		assert(i.cond == core.InstructionClass.ConditionalCodes.EQ);
		this.byteCodeTest(i);
		i = new core.InstructionClass("CNE 0xFFFF");
		assert(i.cond == core.InstructionClass.ConditionalCodes.NE);
		this.byteCodeTest(i);
		i = new core.InstructionClass("CCS 0xFFFF");
		assert(i.cond == core.InstructionClass.ConditionalCodes.CS);
		this.byteCodeTest(i);
		i = new core.InstructionClass("CCC 0xFFFF");
		assert(i.cond == core.InstructionClass.ConditionalCodes.CC);
		this.byteCodeTest(i);
		i = new core.InstructionClass("CPL 0xFFFF");
		assert(i.cond == core.InstructionClass.ConditionalCodes.PL);
		this.byteCodeTest(i);
		i = new core.InstructionClass("CMI 0xFFFF");
		assert(i.cond == core.InstructionClass.ConditionalCodes.MI);
		this.byteCodeTest(i);
		i = new core.InstructionClass("CHI 0xFFFF");
		assert(i.cond == core.InstructionClass.ConditionalCodes.HI);
		this.byteCodeTest(i);
		i = new core.InstructionClass("CLS 0xFFFF");
		assert(i.cond == core.InstructionClass.ConditionalCodes.LS);
		this.byteCodeTest(i);
		i = new core.InstructionClass("CGE 0xFFFF");
		assert(i.cond == core.InstructionClass.ConditionalCodes.GE);
		this.byteCodeTest(i);
		i = new core.InstructionClass("CGT 0xFFFF");
		assert(i.cond == core.InstructionClass.ConditionalCodes.GT);
		this.byteCodeTest(i);
		i = new core.InstructionClass("CLE 0xFFFF");
		assert(i.cond == core.InstructionClass.ConditionalCodes.LE);
		this.byteCodeTest(i);
		i = new core.InstructionClass("CLT 0xFFFF");
		assert(i.cond == core.InstructionClass.ConditionalCodes.LT);
		this.byteCodeTest(i);
		
		System.out.println("Instruction Parsers OK");
	}

	public static void main(String args[]){
		new InstructionTest();
	}
}
